#!/usr/bin/env python
# coding: utf-8

import re
import gzip
import sys
from itertools import islice

GO_TYPES = ['P', 'F', 'C']

def parse_go_funcs(s):
    d = {}
    for tf in s.split():
        t,f = tf.split(':')
        assert t not in d
        d[t] = frozenset(f.split(','))
    return d

def is_entry_equal_full(d1, d2):
    if d1.keys() != d2.keys():
        return False
    for t in d1:
        if d1[t].difference(d2[t]) and d2[t].difference(d1[t]):
            return False
    return True

def is_entry_equal_types(s1, s2):
    assert s1 or s2
    if s1.difference(s2) and s2.difference(s1):
        return False
    return True


def main_full(compare_type, pred_func_fname):
    assert compare_type in ['exact', 'entry']
    real_funcs = set([line.strip() for line in sys.stdin])
    discarded = set()
    
    pw_size = len(real_funcs)
    results = [(0, pw_size)]

    line_id = 0
    for line in gzip.open(pred_func_fname):
        line = line.strip()
        if not line:
            continue
        line_id += 1
        pred_func = line.split('\t')[1].strip()
        if compare_type == 'exact':
            if pred_func in real_funcs:
                real_funcs.discard(pred_func)
                discarded.add(pred_func)
                results.append((line_id, len(real_funcs)))
            elif pred_func in discarded:
                line_id -= 1
        elif compare_type == 'entry':
            pfd = parse_go_funcs(pred_func)
            found = False
            for rf in list(real_funcs):
                rfd = parse_go_funcs(rf)
                if is_entry_equal_full(rfd, pfd):
                    real_funcs.discard(rf)
                    discarded.add(rf)
                    found = True
            if found:
                results.append((line_id, len(real_funcs)))
            else:                
                for rf in discarded:
                    rfd = parse_go_funcs(rf)
                    if is_entry_equal_full(rfd, pfd):
                        line_id -= 1
                        break
        if not real_funcs or line_id > max(500, pw_size):
            break

    return ' '.join('%d:%d' % (i,n) for i,n in results)

def main_types(compare_type, pred_func_fname):
    assert compare_type in ['exact', 'entry']

    real_funcs_dict = dict((t, set()) for t in GO_TYPES)
    for line in sys.stdin:
        line = line.strip()
        if not line:
            continue
        for t,f in parse_go_funcs(line).items():
            real_funcs_dict[t].add(f)

    discarded = dict((t, set()) for t in GO_TYPES)

    pw_size = max(len(f) for f in real_funcs_dict.itervalues())
    results = dict((t, [(0, len(real_funcs_dict[t]))]) for t in GO_TYPES)

    line_ids = dict((t,0) for t in GO_TYPES)
    for line in gzip.open(pred_func_fname):
        line = line.strip()
        if not line:
            continue
        for t in GO_TYPES:
            line_ids[t] += 1
        pred_func = line.split('\t')[1].strip()
        pfd = parse_go_funcs(pred_func)
        for t,pf in pfd.items():
            if compare_type == 'exact':
                if pf in real_funcs_dict[t]:
                    real_funcs_dict[t].discard(pf)
                    discarded[t].add(pf)
                    results[t].append((line_ids[t], len(real_funcs_dict[t])))
                elif pf in discarded[t]:
                    line_ids[t] -= 1
            elif compare_type == 'entry':
                found = False
                for rf in list(real_funcs_dict[t]):
                    if is_entry_equal_types(rf, pf):
                        real_funcs_dict[t].discard(rf)
                        discarded[t].add(rf)
                        found = True
                if found:
                    results[t].append((line_ids[t], len(real_funcs_dict[t])))
                else:
                    for rf in discarded[t]:
                        if is_entry_equal_types(rf, pf):
                            line_ids[t] -= 1
                            break

        if sum(len(real_funcs_dict[t]) for t in real_funcs_dict) == 0 or min(line_ids.values()) > max(500, pw_size):
            break

    return '|'.join('%s %s' % (t, ' '.join('%d:%d' % (i,n) for i,n in results[t])) for t in GO_TYPES)


def main():
   
    compare_type = sys.argv[1].strip()
    assert compare_type in ['full', 'types']

    compare_func = sys.argv[2].strip()
    pred_func_fname = sys.argv[3].strip()

    if compare_type == 'full':
        res = main_full(compare_func, pred_func_fname)
    elif compare_type == 'types':
        res = main_types(compare_func, pred_func_fname) 

    print res


if __name__ == "__main__":
    main()

